package com.example.downlinetext;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.Shader;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import androidx.annotation.NonNull;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Iterator;

public class moveSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable, View.OnTouchListener {

    private SurfaceHolder surfaceHolder;
    private int maxLen = 15;    //最大轨迹长度
    private float addWidth = 3f;    //刀光增量宽度
    private boolean isDiff = false;

    private Deque<PointF> pointFS = new ArrayDeque<>(maxLen);   //刀光上边框点集合
    private Deque<PointF> pointFSClose = new ArrayDeque<>(maxLen);  //刀光下边框点集合

    private Paint mPaint = new Paint();
    private Path mPath = new Path();
    private Message message = new Message();
    private Canvas mCanvas;
    private Shader mShader;//刀光填充颜色
    Runnable diff = new Runnable() {
        @Override
        public void run() {
            PointF pointF = pointFS.pollFirst();
            int delayMillis = 50;
            if (null != pointF) {
                postInvalidate();
                postDelayed(diff, delayMillis);
                return;
            }

            if (isDiff) {
                postDelayed(diff, delayMillis);
            }
        }
    };

    //刀光清空
    Runnable clearP = new Runnable() {
        @Override
        public void run() {
            pointFS.clear();
            postInvalidate();
        }
    };


    public moveSurfaceView(Context context) {
        super(context);
        init();
    }

    public moveSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public moveSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


    private void init() {
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setFormat(PixelFormat.TRANSPARENT);
        this.setKeepScreenOn(true);
        setOnTouchListener(this);
        setFocusable(true);
        setFocusableInTouchMode(true);
        int[] colors = {Color.RED, Color.GREEN, Color.BLUE};
        float[] position = {0f, 0.3f, 1.0f};
        mShader = new LinearGradient(0, 0, getMeasuredWidth(), 0, colors, position, Shader.TileMode.CLAMP);
        mPaint.setAntiAlias(true);
    }


    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {

        new Thread(this::run).start();
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
        new Thread(this::run).start();
    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) {

    }
    private Path creatPath() {
        PointF start = pointFS.peek();

        Path path = new Path();
        path.moveTo(start.x, start.y);

        int width = 1;

        PointF pre = null;
        PointF next = null;

        for (Iterator<PointF> iter = pointFS.iterator(); iter.hasNext(); ) {
            next = iter.next();
            if (iter.hasNext()) {

                float v = width / 2;
                float k = 0; //计算斜率，解决45°角为一条线的BUG
                if (pre != null) k = (next.y - pre.y) / (next.x - pre.x);
                if (Math.abs(1 - k) < 0.9) {
                    path.lineTo(next.x, next.y - v);
                    pointFSClose.addFirst(new PointF(next.x, next.y + v));
                } else {
                    path.lineTo(next.x - v, next.y - v);
                    pointFSClose.addFirst(new PointF(next.x + v, next.y + v));
                }

                pre = next;
            } else {
                path.lineTo(next.x, next.y);
            }

            width += addWidth;
        }

        for (; pointFSClose.peekFirst() != null; ) {
            PointF pf = pointFSClose.pollFirst();
            path.lineTo(pf.x, pf.y);
        }
        path.close();

        return path;
    }

    public void reDraw() {
        try {
            mCanvas = surfaceHolder.lockCanvas();
            PointF start = pointFS.peek();
            Log.d("TAG","start:");
            if (start == null) return;
            Log.d("TAG","start:1");
            Path path = creatPath();
            mCanvas.drawPath(path, mPaint);

            //填充
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setShader(mShader);
            mCanvas.drawPath(path, mPaint);
        } catch (Exception e) {

        } finally {
            if (mCanvas != null) {
                surfaceHolder.unlockCanvasAndPost(mCanvas);
            }
        }

    }

    @Override
    public void run() {
        if (isDiff){
            reDraw();
        }
    }
    private void onMove(float x, float y) {
        if (pointFS.size() >= maxLen - 1) {
            pointFS.pollFirst();
        }
        pointFS.addLast(new PointF(x, y));
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isDiff = true;
                postDelayed(diff, 80);
                pointFS.clear();
                pointFS.addLast(new PointF(event.getX(), event.getY()));
                postInvalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                onMove(event.getX() , event.getY());
                postInvalidate();
                break;
            case MotionEvent.ACTION_UP:
                isDiff = false;
                postDelayed(clearP, 400);
                break;
        }
        return true;//ture 才开始画画
    }
}
